package com.sdjzu.wangfuying.androidusbserialportlib.util;
/*
作者：王福迎
邮箱：<805447391@qq.com>
网址：https://gitee.com/wangfuying_admin
*/

import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.FragmentActivity;

import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.util.SerialInputOutputManager;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Connection implements LifecycleObserver {
    private static final int MSG_DATA = 0x0001;
    private static final int MSG_ERROR = 0x0002;
    private final UsbSerialPort usbSerialPort;
    private final Context context;
    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    private OnConnectionMessageListener listener;
    private SerialInputOutputManager mSerialIoManager;
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void dispatchMessage(Message msg) {
            switch (msg.what) {
                case MSG_DATA:
                    listener.onData(Connection.this, (byte[]) msg.obj);
                    break;
                case MSG_ERROR:
                    listener.onError(Connection.this, (Exception) msg.obj);
                    break;
                default:
                    super.dispatchMessage(msg);
            }
        }
    };

    Connection(Context context, UsbSerialPort usbSerialPort) {
        this.context = context;
        this.usbSerialPort = usbSerialPort;
    }

    public Connection setListener(OnConnectionMessageListener listener) {
        this.listener = listener;
        return this;
    }

    public Connection setParamters(int baudRate, int dataBits, int stopBits, int parity) {
        try {
            usbSerialPort.setParameters(baudRate, dataBits, stopBits, parity);
        } catch (Exception e) {
            listener.onError(this, e);
        }
        return this;
    }


    public Connection open() {
        final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        assert usbManager != null;
        try {
            UsbDeviceConnection connection = usbManager.openDevice(usbSerialPort.getDriver().getDevice());
            usbSerialPort.open(connection);
        } catch (Exception e) {
            listener.onError(this, e);
        }
        startIoManager();
        listener.onOpened(this);
        return this;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(LifecycleOwner activity) {
        close();
    }

    public Connection close() {
        stopIoManager();
        try {
            usbSerialPort.close();
        } catch (IOException e) {
            listener.onError(this, e);
        }

        listener.onClosed(this);
        return this;
    }

    private void stopIoManager() {
        if (mSerialIoManager != null) {
            mSerialIoManager.stop();
            mSerialIoManager = null;
        }
    }

    private void startIoManager() {
        if (usbSerialPort != null) {
            mSerialIoManager = new SerialInputOutputManager(usbSerialPort, new SerialInputOutputManager.Listener() {
                @Override
                public void onNewData(byte[] data) {
                    Message message = new Message();
                    message.what = MSG_DATA;
                    message.obj = data;
                    handler.sendMessage(message);
                }

                @Override
                public void onRunError(Exception e) {
                    Message message = new Message();
                    message.what = MSG_ERROR;
                    message.obj = e;
                    handler.sendMessage(message);
                }
            });
            mExecutor.submit(mSerialIoManager);
        }
    }

    public Connection writeSync(byte[] data) {
        if (mSerialIoManager != null) {
            mSerialIoManager.writeSync(data);
        }
        return this;
    }

    public Connection writeAsync(byte[] data) {
        if (mSerialIoManager != null) {
            mSerialIoManager.writeAsync(data);
        }
        return this;
    }

    public Connection autoClose() {
        if (context instanceof FragmentActivity) {
            ((FragmentActivity) context).getLifecycle().addObserver(this);
        }
        return this;
    }

    public Connection cancelAutoClose() {
        if (context instanceof FragmentActivity) {
            ((FragmentActivity) context).getLifecycle().removeObserver(this);
        }
        return this;
    }

    public OnConnectionMessageListener getListener() {
        return listener;
    }
}
